<template>
  <div class="canvasTransform">
    <canvas id="distort" ref="distortRef" width="900" height="900"></canvas>
    <!-- distort 变形 -->
  </div>
</template>

<script lang="ts">
import { Vue, Options } from 'vue-property-decorator';
@Options({ components: {

} })
export default class CanvasTransform extends Vue {
  public ctx: CanvasRenderingContext2D |null = null;

  public draw() {
    // this.canvasSave();
    // this.drawRotateCircle();
    // this.drawScale();
    // this.clearCanvas();
    this.clipPath();
  }
  public clipPath() {
    this.ctx!.fillRect(0, 0, 150, 150);
    this.ctx!.translate(75, 75);

    // Create a circular clipping path
    this.ctx!.beginPath();
    this.ctx!.arc(0, 0, 60, 0, Math.PI * 2, true);
    this.ctx!.clip();

    // draw background
    const lingrad = this.ctx!.createLinearGradient(0, -75, 0, 75);
    lingrad.addColorStop(0, '#232256');
    lingrad.addColorStop(1, '#143778');
    this.ctx!.fillStyle = lingrad;
    this.ctx!.fillRect(-75, -75, 150, 150);

    // draw stars
    for (let j = 1;j < 50;j++) {
      this.ctx!.save();
      this.ctx!.fillStyle = '#fff';
      this.ctx!.translate(
        75 - Math.floor(Math.random() * 150),
        75 - Math.floor(Math.random() * 150),
      );
      this.drawStar(this.ctx!, Math.floor(Math.random() * 4) + 2);
      this.ctx!.restore();
    }
  }
  public drawStar(ctx: CanvasRenderingContext2D, r: number) {
    ctx.save();
    ctx.beginPath();
    ctx.moveTo(r, 0);
    for (let i = 0;i < 9;i++) {
      ctx.rotate(Math.PI / 5);
      if (i % 2 === 0) {
        ctx.lineTo((r / 0.525731) * 0.200811, 0);
      } else {
        ctx.lineTo(r, 0);
      }
    }
    ctx.closePath();
    ctx.fill();
    ctx.restore();
  }
  public clearCanvas() {
    const canvas = this.$refs.distortRef as HTMLCanvasElement;

    this.ctx!.beginPath();
    this.ctx!.fillStyle = '#ff0';
    this.ctx!.fillRect(0, 0, canvas.width, canvas.height);

    // 绘制蓝色三角形
    this.ctx!.beginPath();
    this.ctx!.fillStyle = 'blue';
    this.ctx!.moveTo(20, 20);
    this.ctx!.lineTo(180, 20);
    this.ctx!.lineTo(130, 130);
    // this.ctx!.closePath();
    this.ctx!.fill();

    // 清除一部分画布
    this.ctx!.clearRect(10, 10, 120, 100);
    // 请确保在调用 clearRect()之后绘制新内容前调用beginPath() 。
  }
  public drawScale() {
    this.ctx!.save();
    this.ctx!.scale(10, 3);
    this.ctx!.fillRect(1, 10, 10, 10);
    this.ctx!.restore();
    this.ctx!.scale(-1, 1);
    this.ctx!.font = '48px serif';
    this.ctx!.fillText('MDN', -135, 120);
  }
  public drawRotateCircle() {
    this.ctx!.translate(75, 75);
    for (let i = 1;i < 6;i++) { // Loop through rings (from inside to out)
      this.ctx!.save();
      this.ctx!.fillStyle = `rgb(${51 * i},${255 - 51 * i},255)`;
      for (let j = 0;j < i * 6;j++) { // draw individual dots
        this.ctx!.rotate(Math.PI * 2 / (i * 6));
        this.ctx!.beginPath();
        this.ctx!.arc(0, i * 12.5, 5, 0, Math.PI * 2, true);
        this.ctx!.fill();
      }
      this.ctx!.restore();
    }
  }
  public canvasSave() {
    this.ctx!.save();
    // save 和 restore 方法是用来保存和恢复 canvas 状态的，都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形以及当前裁剪路径的一个快照。
    this.ctx!.fillStyle = 'green';
    this.ctx!.fillRect(10, 10, 100, 100);
    this.ctx!.restore();
    this.ctx!.fillRect(150, 75, 100, 100);
  }
  public mounted() {
    const canvas = this.$refs.distortRef as HTMLCanvasElement;
    this.ctx = canvas.getContext('2d');
    this.draw();
  }
};
</script>

<style lang="postcss">
.canvasTransform{
  position: relative;
  width: 100%;
  height: 100%;
  #distort{
    position: absolute;
    left: 0;
    top: 0;
    background-color: #fff;
  }
}

</style>
